#include "MainWindow.h"

#include <iostream>
#include <QtGui>
#include <QDateTime>

#include "Clock.h"
#include "FieldCreation.h"
#include "CurrentCreation.h"
#include "Pulse.h"
#include "MultiLayer.h"
#include "Output.h"
#include "TrajSimul.h"
#include "AstroidSimul.h"
#include "LoopSimul.h"
#include "ICritvsLengthAlgo.h"
#include "ICritvsLengthDiffHAlgo.h"
#include "PhDSimul.h"
#include "CurrentvsLengthSimul.h"
#include "TrajMeanSimul.h"
#include "PhDMeanSimul.h"
#include "InitialPosition.h"

MainWindow::MainWindow() 
{
  QTextStream cout(stdout,QIODevice::WriteOnly);
  QTextStream cin(stdin,QIODevice::ReadOnly);

  setFixedSize(700,700);
  setWindowTitle("MacroLLG Simulation");
  QGridLayout *layout = new QGridLayout(this);
 
  QPushButton *open_button = new QPushButton("Load Parameters");
  QPushButton *save_button = new QPushButton("Save Parameters");
  QPushButton *saveAs_button = new QPushButton("Save as");
  QPushButton *run_button = new QPushButton("Run");
  QPushButton *exit_button = new QPushButton("Exit");
  layout->addWidget(open_button,0,0,1,1);  
  layout->addWidget(save_button,0,1,1,1);
  layout->addWidget(saveAs_button,0,2,1,1);
  layout->addWidget(run_button,5,3,1,1);
  layout->addWidget(exit_button,6,3,1,1);

  sampleWindow = new SampleWindow();
  simulationWindow = new SimulationWindow();
  currentWindow = new CurrentWindow(mainParams);
  fieldWindow = new FieldWindow();
  outputWindow = new OutputWindow(); 
  QTabWidget *tab = new QTabWidget(this);
  tab->addTab(simulationWindow,"Simulation");
  tab->addTab(currentWindow,"Current");
  tab->addTab(fieldWindow,"Field");
  tab->addTab(sampleWindow,"Sample");
  tab->addTab(outputWindow,"Output File");
  layout->addWidget(tab,1,0,4,4);

  fileName="../Parameters.xml";
  mainParams.getParameters(fileName);
  sendParameters();
  //progressDialog = new QProgressDialog("Computing","Cancel",0,100);


  //QWidget::connect(run_button,SIGNAL(clicked()),progressWindow,SLOT(show()));
  QWidget::connect(run_button,SIGNAL(clicked()),this,SLOT(runSimulation()));
  QWidget::connect(exit_button,SIGNAL(clicked()),qApp,SLOT(quit()));
  QWidget::connect(open_button,SIGNAL(clicked()),this,SLOT(loadParameters()));
  QWidget::connect(save_button,SIGNAL(clicked()),this,SLOT(saveParameters()));
  QWidget::connect(saveAs_button,SIGNAL(clicked()),this,SLOT(saveDialog())); 
  QWidget::connect(simulationWindow,SIGNAL(constantIChoice()),currentWindow,SLOT(showTraj()));
  QWidget::connect(simulationWindow,SIGNAL(loopHChoice()),fieldWindow,SLOT(showLoop()));
  QWidget::connect(simulationWindow,SIGNAL(constantHChoice()),fieldWindow,SLOT(showTraj()));
  QWidget::connect(simulationWindow,SIGNAL(loopIChoice()),currentWindow,SLOT(showILoop()));
  QWidget::connect(simulationWindow,SIGNAL(loopLengthChoice()),currentWindow,SLOT(showLengthLoop()));
  QWidget::connect(simulationWindow,SIGNAL(astroidChoice()),currentWindow,SLOT(showTraj()));
  QWidget::connect(simulationWindow,SIGNAL(astroidChoice()),fieldWindow,SLOT(showAstroid()));

  //  QWidget::connect(progressWindow->cancel,SIGNAL(clicked()),thread,SLOT(quit()));

}

MainWindow::~MainWindow()
{

}

void MainWindow::getParameters()
{
  mainParams = currentWindow->getParameters(mainParams);
  mainParams = fieldWindow->getParameters(mainParams);
  mainParams = simulationWindow->getParameters(mainParams);
  mainParams = sampleWindow->getParameters(mainParams);
  outputFile=outputWindow->getFileName();
  sortFileName();
}
void MainWindow::sendParameters()
{
  fieldWindow->loadParameters(mainParams);
  sampleWindow->loadParameters(mainParams);
  currentWindow->loadParameters(mainParams);
  simulationWindow->loadParameters(mainParams);
}

void MainWindow::loadParameters()
{
  fileName = QFileDialog::getOpenFileName(this,"Load Parameters",QString(),"Parameters (*.xml)");
  mainParams.getParameters(fileName);
  sendParameters();
}

void MainWindow::saveParameters()
{
  getParameters();
  mainParams.saveParameters(fileName);
}

void MainWindow::saveDialog()
{
  fileName = QFileDialog::getSaveFileName(this,"Save Parameters",QString(),"Parameters (*.xml)");
  getParameters();
  mainParams.saveParameters(fileName);
}
			 
void MainWindow::runSimulation()
{
  int choice = simulationWindow->getSimChoice();
  int phdchoice = simulationWindow->getXAxis()->currentIndex();
  getParameters();

  Clock clock=Clock(mainParams);
  
  CurrentCreation *currentfactory=new CurrentCreation();
  Pulse *current=currentfactory->NewPulse(mainParams);
  current->Current(mainParams);

  FieldCreation * fieldfactory=new FieldCreation();
  Pulse * field=fieldfactory->NewPulse(mainParams);
  field->Field(mainParams);
  
  MultiLayer multiLayer=MultiLayer(mainParams);

  Output output;
  output=Output();
  output.initialize(outputFile);

  if(outputWindow->getCopyParams())
    {
      outputFile.remove(".txt");
      QString copyFile = outputFile + "_parameters.txt";
      mainParams.saveParameters(copyFile);
    }

  switch(choice)
    {
    case 0 :
      {
	if(simulationWindow->getTrajAverage() == true)
	  {
	    TrajMeanSimul().solve(clock,output,field,current,multiLayer,mainParams);
	  }
	else
	  {
	    if(simulationWindow->getAngle() == true)
	      {
		multiLayer[multiLayer.getSolveLayer()].setMag(InitialPosition(clock,output,field,current,multiLayer,mainParams)); 
	      }
	    TrajSimul().solve(clock,output,field,current,multiLayer,mainParams);
	  }
	break;
      }
    case 1 :
      {
	if(phdchoice==0)
	  {
	    if(simulationWindow->getPhDAverage() == true)
	      {
		PhDMeanSimul().solve(clock,output,field,current,multiLayer,mainParams);
	      }
	    else
	      {
		PhDSimul().solve(clock,output,field,current,multiLayer,mainParams);
	      }	  
	  }
	else if(phdchoice==1)
	  {
	    CurrentvsLengthSimul().solve(clock,output,field,current,multiLayer,mainParams);
	  }
	break;
      }
    case 2 :
      {
	AstroidSimul().solve(clock,output,field,current,multiLayer,mainParams);
	break;
      }
    case 3 :
      {
	if(simulationWindow->getVariousFields() == false)
	  {
	    ICritvsLengthAlgo().solve(clock,output,field,current,multiLayer,mainParams);
	  }
	else 
	  {
	    ICritvsLengthDiffHAlgo().solve(clock,output,field,current,multiLayer,mainParams);
	  }
	break;
      }
    case 4 :
      {
	LoopSimul().solve(clock,output,field,current,multiLayer,mainParams);
	break;
      }
    }
  QMessageBox::information(this,"Simulation done","The calculation is complete");
  plotWindow = new PlotWindow();
  plotWindow->show();
}

void MainWindow::sortFileName()
{
  QTextStream cout(stdout,QIODevice::WriteOnly);
  QString newName,str;
  int pos,length;
  length=outputFile.length();
  cout<<outputFile<<endl;
  
  if(outputFile.contains("prefix"))
    {
      pos=outputFile.lastIndexOf("txt");
      newName=outputFile.right(length-pos-3);
      newName += "_";
    }
  if(outputFile.contains("simul"))
    {
      int simChoice = simulationWindow->getSimChoice();
      switch (simChoice)
	{
	case 0 :
	  {
	    newName += "traj_";
	    break;
	  }
	case 1 :
	  {
	    newName += "phd_";
	    break;
	  }
	case 2 :
	  {
	    newName += "astroid_";
	    break;
	  }
	case 3 :
	  {
	    newName += "IcVsLength_";
	    break;
	  }
	case 4 :
	  {
	    newName += "loop_";
	    break;
	  }
	}
    }
  if(outputFile.contains("BxxmT"))
    {
      newName += "B";
      newName.append(str.setNum(mainParams.getField()["value"]));
      newName += "T_";
    }
  if(outputFile.contains("IxxmA"))
    {
      newName += "I";
      newName.append(str.setNum(mainParams.getCurrent()["value"]));
      newName += "A_";
    }
  if(outputFile.contains("lxxns"))
    {
      newName += "length";
      newName.append(str.setNum(mainParams.getCurrentPulse()["length"]));
      newName += "s_";
    }
  if(outputFile.contains("date"))
    {
      QDateTime date = QDateTime::currentDateTime();
      newName += date.toString(Qt::ISODate);
    }
  newName.append(".txt");
  newName.replace("_.txt",".txt");
  cout<<newName<<endl;
  outputFile = newName;
}
